3  * Copyright 2016 gRPC authors.
 
   5  * Licensed under the Apache License, Version 2.0 (the "License");
 
   6  * you may not use this file except in compliance with the License.
 
   7  * You may obtain a copy of the License at
 
   9  *     http://www.apache.org/licenses/LICENSE-2.0
 
  11  * Unless required by applicable law or agreed to in writing, software
 
  12  * distributed under the License is distributed on an "AS IS" BASIS,
 
  13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  14  * See the License for the specific language governing permissions and
 
  15  * limitations under the License.
 
  19 #include <grpc/support/port_platform.h>
 
  23 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
 
  24 #include "src/core/lib/iomgr/sockaddr.h"
 
  27 #include <sys/types.h>
 
  30 #include <grpc/support/alloc.h>
 
  31 #include <grpc/support/log.h>
 
  32 #include <grpc/support/string_util.h>
 
  33 #include <grpc/support/time.h>
 
  35 #include <address_sorting/address_sorting.h>
 
  36 #include "src/core/ext/filters/client_channel/parse_address.h"
 
  37 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
 
  38 #include "src/core/lib/gpr/host_port.h"
 
  39 #include "src/core/lib/gpr/string.h"
 
  40 #include "src/core/lib/iomgr/combiner.h"
 
  41 #include "src/core/lib/iomgr/error.h"
 
  42 #include "src/core/lib/iomgr/executor.h"
 
  43 #include "src/core/lib/iomgr/iomgr_internal.h"
 
  44 #include "src/core/lib/iomgr/nameser.h"
 
  45 #include "src/core/lib/iomgr/sockaddr_utils.h"
 
  47 using grpc_core::ServerAddress;
 
  48 using grpc_core::ServerAddressList;
 
  50 grpc_core::TraceFlag grpc_trace_cares_address_sorting(false,
 
  51                                                       "cares_address_sorting");
 
  53 grpc_core::TraceFlag grpc_trace_cares_resolver(false, "cares_resolver");
 
  55 struct grpc_ares_request {
 
  56   /** indicates the DNS server to use, if specified */
 
  57   struct ares_addr_port_node dns_server_addr;
 
  58   /** following members are set in grpc_resolve_address_ares_impl */
 
  59   /** closure to call when the request completes */
 
  60   grpc_closure* on_done;
 
  61   /** the pointer to receive the resolved addresses */
 
  62   grpc_core::UniquePtr<grpc_core::ServerAddressList>* addresses_out;
 
  63   /** the pointer to receive the service config in JSON */
 
  64   char** service_config_json_out;
 
  65   /** the evernt driver used by this request */
 
  66   grpc_ares_ev_driver* ev_driver;
 
  67   /** number of ongoing queries */
 
  68   size_t pending_queries;
 
  70   /** the errors explaining query failures, appended to in query callbacks */
 
  74 typedef struct grpc_ares_hostbyname_request {
 
  75   /** following members are set in create_hostbyname_request_locked
 
  77   /** the top-level request instance */
 
  78   grpc_ares_request* parent_request;
 
  79   /** host to resolve, parsed from the name to resolve */
 
  81   /** port to fill in sockaddr_in, parsed from the name to resolve */
 
  83   /** is it a grpclb address */
 
  85 } grpc_ares_hostbyname_request;
 
  87 static void log_address_sorting_list(const ServerAddressList& addresses,
 
  88                                      const char* input_output_str) {
 
  89   for (size_t i = 0; i < addresses.size(); i++) {
 
  91     if (grpc_sockaddr_to_string(&addr_str, &addresses[i].address(), true)) {
 
  92       gpr_log(GPR_INFO, "c-ares address sorting: %s[%" PRIuPTR "]=%s",
 
  93               input_output_str, i, addr_str);
 
  97               "c-ares address sorting: %s[%" PRIuPTR "]=<unprintable>",
 
 103 void grpc_cares_wrapper_address_sorting_sort(ServerAddressList* addresses) {
 
 104   if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_cares_address_sorting)) {
 
 105     log_address_sorting_list(*addresses, "input");
 
 107   address_sorting_sortable* sortables = (address_sorting_sortable*)gpr_zalloc(
 
 108       sizeof(address_sorting_sortable) * addresses->size());
 
 109   for (size_t i = 0; i < addresses->size(); ++i) {
 
 110     sortables[i].user_data = &(*addresses)[i];
 
 111     memcpy(&sortables[i].dest_addr.addr, &(*addresses)[i].address().addr,
 
 112            (*addresses)[i].address().len);
 
 113     sortables[i].dest_addr.len = (*addresses)[i].address().len;
 
 115   address_sorting_rfc_6724_sort(sortables, addresses->size());
 
 116   ServerAddressList sorted;
 
 117   sorted.reserve(addresses->size());
 
 118   for (size_t i = 0; i < addresses->size(); ++i) {
 
 119     sorted.emplace_back(*static_cast<ServerAddress*>(sortables[i].user_data));
 
 122   *addresses = std::move(sorted);
 
 123   if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_cares_address_sorting)) {
 
 124     log_address_sorting_list(*addresses, "output");
 
 128 static void grpc_ares_request_ref_locked(grpc_ares_request* r) {
 
 129   r->pending_queries++;
 
 132 static void grpc_ares_request_unref_locked(grpc_ares_request* r) {
 
 133   r->pending_queries--;
 
 134   if (r->pending_queries == 0u) {
 
 135     grpc_ares_ev_driver_on_queries_complete_locked(r->ev_driver);
 
 139 void grpc_ares_complete_request_locked(grpc_ares_request* r) {
 
 140   /* Invoke on_done callback and destroy the
 
 142   r->ev_driver = nullptr;
 
 143   ServerAddressList* addresses = r->addresses_out->get();
 
 144   if (addresses != nullptr) {
 
 145     grpc_cares_wrapper_address_sorting_sort(addresses);
 
 146     GRPC_ERROR_UNREF(r->error);
 
 147     r->error = GRPC_ERROR_NONE;
 
 148     // TODO(apolcyn): allow c-ares to return a service config
 
 149     // with no addresses along side it
 
 151   GRPC_CLOSURE_SCHED(r->on_done, r->error);
 
 154 static grpc_ares_hostbyname_request* create_hostbyname_request_locked(
 
 155     grpc_ares_request* parent_request, char* host, uint16_t port,
 
 157   GRPC_CARES_TRACE_LOG(
 
 158       "request:%p create_hostbyname_request_locked host:%s port:%d "
 
 160       parent_request, host, port, is_balancer);
 
 161   grpc_ares_hostbyname_request* hr = static_cast<grpc_ares_hostbyname_request*>(
 
 162       gpr_zalloc(sizeof(grpc_ares_hostbyname_request)));
 
 163   hr->parent_request = parent_request;
 
 164   hr->host = gpr_strdup(host);
 
 166   hr->is_balancer = is_balancer;
 
 167   grpc_ares_request_ref_locked(parent_request);
 
 171 static void destroy_hostbyname_request_locked(
 
 172     grpc_ares_hostbyname_request* hr) {
 
 173   grpc_ares_request_unref_locked(hr->parent_request);
 
 178 static void on_hostbyname_done_locked(void* arg, int status, int timeouts,
 
 179                                       struct hostent* hostent) {
 
 180   grpc_ares_hostbyname_request* hr =
 
 181       static_cast<grpc_ares_hostbyname_request*>(arg);
 
 182   grpc_ares_request* r = hr->parent_request;
 
 183   if (status == ARES_SUCCESS) {
 
 184     GRPC_CARES_TRACE_LOG(
 
 185         "request:%p on_hostbyname_done_locked host=%s ARES_SUCCESS", r,
 
 187     if (*r->addresses_out == nullptr) {
 
 188       *r->addresses_out = grpc_core::MakeUnique<ServerAddressList>();
 
 190     ServerAddressList& addresses = **r->addresses_out;
 
 191     for (size_t i = 0; hostent->h_addr_list[i] != nullptr; ++i) {
 
 192       grpc_core::InlinedVector<grpc_arg, 2> args_to_add;
 
 193       if (hr->is_balancer) {
 
 194         args_to_add.emplace_back(grpc_channel_arg_integer_create(
 
 195             const_cast<char*>(GRPC_ARG_ADDRESS_IS_BALANCER), 1));
 
 196         args_to_add.emplace_back(grpc_channel_arg_string_create(
 
 197             const_cast<char*>(GRPC_ARG_ADDRESS_BALANCER_NAME), hr->host));
 
 199       grpc_channel_args* args = grpc_channel_args_copy_and_add(
 
 200           nullptr, args_to_add.data(), args_to_add.size());
 
 201       switch (hostent->h_addrtype) {
 
 203           size_t addr_len = sizeof(struct sockaddr_in6);
 
 204           struct sockaddr_in6 addr;
 
 205           memset(&addr, 0, addr_len);
 
 206           memcpy(&addr.sin6_addr, hostent->h_addr_list[i],
 
 207                  sizeof(struct in6_addr));
 
 208           addr.sin6_family = static_cast<unsigned char>(hostent->h_addrtype);
 
 209           addr.sin6_port = hr->port;
 
 210           addresses.emplace_back(&addr, addr_len, args);
 
 211           char output[INET6_ADDRSTRLEN];
 
 212           ares_inet_ntop(AF_INET6, &addr.sin6_addr, output, INET6_ADDRSTRLEN);
 
 213           GRPC_CARES_TRACE_LOG(
 
 214               "request:%p c-ares resolver gets a AF_INET6 result: \n"
 
 215               "  addr: %s\n  port: %d\n  sin6_scope_id: %d\n",
 
 216               r, output, ntohs(hr->port), addr.sin6_scope_id);
 
 220           size_t addr_len = sizeof(struct sockaddr_in);
 
 221           struct sockaddr_in addr;
 
 222           memset(&addr, 0, addr_len);
 
 223           memcpy(&addr.sin_addr, hostent->h_addr_list[i],
 
 224                  sizeof(struct in_addr));
 
 225           addr.sin_family = static_cast<unsigned char>(hostent->h_addrtype);
 
 226           addr.sin_port = hr->port;
 
 227           addresses.emplace_back(&addr, addr_len, args);
 
 228           char output[INET_ADDRSTRLEN];
 
 229           ares_inet_ntop(AF_INET, &addr.sin_addr, output, INET_ADDRSTRLEN);
 
 230           GRPC_CARES_TRACE_LOG(
 
 231               "request:%p c-ares resolver gets a AF_INET result: \n"
 
 232               "  addr: %s\n  port: %d\n",
 
 233               r, output, ntohs(hr->port));
 
 240     gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
 
 241                  ares_strerror(status));
 
 242     GRPC_CARES_TRACE_LOG("request:%p on_hostbyname_done_locked host=%s %s", r,
 
 243                          hr->host, error_msg);
 
 244     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
 
 246     r->error = grpc_error_add_child(error, r->error);
 
 248   destroy_hostbyname_request_locked(hr);
 
 251 static void on_srv_query_done_locked(void* arg, int status, int timeouts,
 
 252                                      unsigned char* abuf, int alen) {
 
 253   grpc_ares_request* r = static_cast<grpc_ares_request*>(arg);
 
 254   if (status == ARES_SUCCESS) {
 
 255     GRPC_CARES_TRACE_LOG("request:%p on_srv_query_done_locked ARES_SUCCESS", r);
 
 256     struct ares_srv_reply* reply;
 
 257     const int parse_status = ares_parse_srv_reply(abuf, alen, &reply);
 
 258     GRPC_CARES_TRACE_LOG("request:%p ares_parse_srv_reply: %d", r,
 
 260     if (parse_status == ARES_SUCCESS) {
 
 261       ares_channel* channel =
 
 262           grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
 
 263       for (struct ares_srv_reply* srv_it = reply; srv_it != nullptr;
 
 264            srv_it = srv_it->next) {
 
 265         if (grpc_ares_query_ipv6()) {
 
 266           grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked(
 
 267               r, srv_it->host, htons(srv_it->port), true /* is_balancer */);
 
 268           ares_gethostbyname(*channel, hr->host, AF_INET6,
 
 269                              on_hostbyname_done_locked, hr);
 
 271         grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked(
 
 272             r, srv_it->host, htons(srv_it->port), true /* is_balancer */);
 
 273         ares_gethostbyname(*channel, hr->host, AF_INET,
 
 274                            on_hostbyname_done_locked, hr);
 
 275         grpc_ares_ev_driver_start_locked(r->ev_driver);
 
 278     if (reply != nullptr) {
 
 279       ares_free_data(reply);
 
 283     gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
 
 284                  ares_strerror(status));
 
 285     GRPC_CARES_TRACE_LOG("request:%p on_srv_query_done_locked %s", r,
 
 287     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
 
 289     r->error = grpc_error_add_child(error, r->error);
 
 291   grpc_ares_request_unref_locked(r);
 
 294 static const char g_service_config_attribute_prefix[] = "grpc_config=";
 
 296 static void on_txt_done_locked(void* arg, int status, int timeouts,
 
 297                                unsigned char* buf, int len) {
 
 299   grpc_ares_request* r = static_cast<grpc_ares_request*>(arg);
 
 300   const size_t prefix_len = sizeof(g_service_config_attribute_prefix) - 1;
 
 301   struct ares_txt_ext* result = nullptr;
 
 302   struct ares_txt_ext* reply = nullptr;
 
 303   grpc_error* error = GRPC_ERROR_NONE;
 
 304   if (status != ARES_SUCCESS) goto fail;
 
 305   GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked ARES_SUCCESS", r);
 
 306   status = ares_parse_txt_reply_ext(buf, len, &reply);
 
 307   if (status != ARES_SUCCESS) goto fail;
 
 308   // Find service config in TXT record.
 
 309   for (result = reply; result != nullptr; result = result->next) {
 
 310     if (result->record_start &&
 
 311         memcmp(result->txt, g_service_config_attribute_prefix, prefix_len) ==
 
 316   // Found a service config record.
 
 317   if (result != nullptr) {
 
 318     size_t service_config_len = result->length - prefix_len;
 
 319     *r->service_config_json_out =
 
 320         static_cast<char*>(gpr_malloc(service_config_len + 1));
 
 321     memcpy(*r->service_config_json_out, result->txt + prefix_len,
 
 323     for (result = result->next; result != nullptr && !result->record_start;
 
 324          result = result->next) {
 
 325       *r->service_config_json_out = static_cast<char*>(
 
 326           gpr_realloc(*r->service_config_json_out,
 
 327                       service_config_len + result->length + 1));
 
 328       memcpy(*r->service_config_json_out + service_config_len, result->txt,
 
 330       service_config_len += result->length;
 
 332     (*r->service_config_json_out)[service_config_len] = '\0';
 
 333     GRPC_CARES_TRACE_LOG("request:%p found service config: %s", r,
 
 334                          *r->service_config_json_out);
 
 337   ares_free_data(reply);
 
 340   gpr_asprintf(&error_msg, "C-ares TXT lookup status is not ARES_SUCCESS: %s",
 
 341                ares_strerror(status));
 
 342   error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
 
 343   GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked %s", r, error_msg);
 
 345   r->error = grpc_error_add_child(error, r->error);
 
 347   grpc_ares_request_unref_locked(r);
 
 350 void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
 
 351     grpc_ares_request* r, const char* dns_server, const char* name,
 
 352     const char* default_port, grpc_pollset_set* interested_parties,
 
 353     bool check_grpclb, int query_timeout_ms, grpc_combiner* combiner) {
 
 354   grpc_error* error = GRPC_ERROR_NONE;
 
 355   grpc_ares_hostbyname_request* hr = nullptr;
 
 356   ares_channel* channel = nullptr;
 
 357   /* parse name, splitting it into host and port parts */
 
 360   gpr_split_host_port(name, &host, &port);
 
 361   if (host == nullptr) {
 
 362     error = grpc_error_set_str(
 
 363         GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
 
 364         GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
 
 366   } else if (port == nullptr) {
 
 367     if (default_port == nullptr) {
 
 368       error = grpc_error_set_str(
 
 369           GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
 
 370           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
 
 373     port = gpr_strdup(default_port);
 
 375   error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties,
 
 376                                             query_timeout_ms, combiner, r);
 
 377   if (error != GRPC_ERROR_NONE) goto error_cleanup;
 
 378   channel = grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
 
 379   // If dns_server is specified, use it.
 
 380   if (dns_server != nullptr) {
 
 381     GRPC_CARES_TRACE_LOG("request:%p Using DNS server %s", r, dns_server);
 
 382     grpc_resolved_address addr;
 
 383     if (grpc_parse_ipv4_hostport(dns_server, &addr, false /* log_errors */)) {
 
 384       r->dns_server_addr.family = AF_INET;
 
 385       struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(addr.addr);
 
 386       memcpy(&r->dns_server_addr.addr.addr4, &in->sin_addr,
 
 387              sizeof(struct in_addr));
 
 388       r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
 
 389       r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
 
 390     } else if (grpc_parse_ipv6_hostport(dns_server, &addr,
 
 391                                         false /* log_errors */)) {
 
 392       r->dns_server_addr.family = AF_INET6;
 
 393       struct sockaddr_in6* in6 =
 
 394           reinterpret_cast<struct sockaddr_in6*>(addr.addr);
 
 395       memcpy(&r->dns_server_addr.addr.addr6, &in6->sin6_addr,
 
 396              sizeof(struct in6_addr));
 
 397       r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
 
 398       r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
 
 400       error = grpc_error_set_str(
 
 401           GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
 
 402           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
 
 405     int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
 
 406     if (status != ARES_SUCCESS) {
 
 408       gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
 
 409                    ares_strerror(status));
 
 410       error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
 
 415   r->pending_queries = 1;
 
 416   if (grpc_ares_query_ipv6()) {
 
 417     hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port),
 
 418                                           false /* is_balancer */);
 
 419     ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked,
 
 422   hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port),
 
 423                                         false /* is_balancer */);
 
 424   ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_locked,
 
 427     /* Query the SRV record */
 
 428     grpc_ares_request_ref_locked(r);
 
 430     gpr_asprintf(&service_name, "_grpclb._tcp.%s", host);
 
 431     ares_query(*channel, service_name, ns_c_in, ns_t_srv,
 
 432                on_srv_query_done_locked, r);
 
 433     gpr_free(service_name);
 
 435   if (r->service_config_json_out != nullptr) {
 
 436     grpc_ares_request_ref_locked(r);
 
 438     gpr_asprintf(&config_name, "_grpc_config.%s", host);
 
 439     ares_search(*channel, config_name, ns_c_in, ns_t_txt, on_txt_done_locked,
 
 441     gpr_free(config_name);
 
 443   grpc_ares_ev_driver_start_locked(r->ev_driver);
 
 444   grpc_ares_request_unref_locked(r);
 
 450   GRPC_CLOSURE_SCHED(r->on_done, error);
 
 455 static bool inner_resolve_as_ip_literal_locked(
 
 456     const char* name, const char* default_port,
 
 457     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs, char** host,
 
 458     char** port, char** hostport) {
 
 459   gpr_split_host_port(name, host, port);
 
 460   if (*host == nullptr) {
 
 462             "Failed to parse %s to host:port while attempting to resolve as ip "
 
 467   if (*port == nullptr) {
 
 468     if (default_port == nullptr) {
 
 470               "No port or default port for %s while attempting to resolve as "
 
 475     *port = gpr_strdup(default_port);
 
 477   grpc_resolved_address addr;
 
 478   GPR_ASSERT(gpr_join_host_port(hostport, *host, atoi(*port)));
 
 479   if (grpc_parse_ipv4_hostport(*hostport, &addr, false /* log errors */) ||
 
 480       grpc_parse_ipv6_hostport(*hostport, &addr, false /* log errors */)) {
 
 481     GPR_ASSERT(*addrs == nullptr);
 
 482     *addrs = grpc_core::MakeUnique<ServerAddressList>();
 
 483     (*addrs)->emplace_back(addr.addr, addr.len, nullptr /* args */);
 
 489 static bool resolve_as_ip_literal_locked(
 
 490     const char* name, const char* default_port,
 
 491     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
 
 492   char* host = nullptr;
 
 493   char* port = nullptr;
 
 494   char* hostport = nullptr;
 
 495   bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs,
 
 496                                                 &host, &port, &hostport);
 
 503 static bool target_matches_localhost_inner(const char* name, char** host,
 
 505   if (!gpr_split_host_port(name, host, port)) {
 
 506     gpr_log(GPR_ERROR, "Unable to split host and port for name: %s", name);
 
 509   if (gpr_stricmp(*host, "localhost") == 0) {
 
 516 static bool target_matches_localhost(const char* name) {
 
 517   char* host = nullptr;
 
 518   char* port = nullptr;
 
 519   bool out = target_matches_localhost_inner(name, &host, &port);
 
 525 #ifdef GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY
 
 526 static bool inner_maybe_resolve_localhost_manually_locked(
 
 527     const char* name, const char* default_port,
 
 528     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs, char** host,
 
 530   gpr_split_host_port(name, host, port);
 
 531   if (*host == nullptr) {
 
 533             "Failed to parse %s into host:port during manual localhost "
 
 538   if (*port == nullptr) {
 
 539     if (default_port == nullptr) {
 
 541               "No port or default port for %s during manual localhost "
 
 546     *port = gpr_strdup(default_port);
 
 548   if (gpr_stricmp(*host, "localhost") == 0) {
 
 549     GPR_ASSERT(*addrs == nullptr);
 
 550     *addrs = grpc_core::MakeUnique<grpc_core::ServerAddressList>();
 
 551     uint16_t numeric_port = grpc_strhtons(*port);
 
 552     // Append the ipv6 loopback address.
 
 553     struct sockaddr_in6 ipv6_loopback_addr;
 
 554     memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr));
 
 555     ((char*)&ipv6_loopback_addr.sin6_addr)[15] = 1;
 
 556     ipv6_loopback_addr.sin6_family = AF_INET6;
 
 557     ipv6_loopback_addr.sin6_port = numeric_port;
 
 558     (*addrs)->emplace_back(&ipv6_loopback_addr, sizeof(ipv6_loopback_addr),
 
 560     // Append the ipv4 loopback address.
 
 561     struct sockaddr_in ipv4_loopback_addr;
 
 562     memset(&ipv4_loopback_addr, 0, sizeof(ipv4_loopback_addr));
 
 563     ((char*)&ipv4_loopback_addr.sin_addr)[0] = 0x7f;
 
 564     ((char*)&ipv4_loopback_addr.sin_addr)[3] = 0x01;
 
 565     ipv4_loopback_addr.sin_family = AF_INET;
 
 566     ipv4_loopback_addr.sin_port = numeric_port;
 
 567     (*addrs)->emplace_back(&ipv4_loopback_addr, sizeof(ipv4_loopback_addr),
 
 569     // Let the address sorter figure out which one should be tried first.
 
 570     grpc_cares_wrapper_address_sorting_sort(addrs->get());
 
 576 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
 
 577     const char* name, const char* default_port,
 
 578     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
 
 579   char* host = nullptr;
 
 580   char* port = nullptr;
 
 581   bool out = inner_maybe_resolve_localhost_manually_locked(name, default_port,
 
 582                                                            addrs, &host, &port);
 
 587 #else  /* GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY */
 
 588 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
 
 589     const char* name, const char* default_port,
 
 590     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
 
 593 #endif /* GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY */
 
 595 static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
 
 596     const char* dns_server, const char* name, const char* default_port,
 
 597     grpc_pollset_set* interested_parties, grpc_closure* on_done,
 
 598     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs,
 
 599     bool check_grpclb, char** service_config_json, int query_timeout_ms,
 
 600     grpc_combiner* combiner) {
 
 601   grpc_ares_request* r =
 
 602       static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
 
 603   r->ev_driver = nullptr;
 
 604   r->on_done = on_done;
 
 605   r->addresses_out = addrs;
 
 606   r->service_config_json_out = service_config_json;
 
 607   r->error = GRPC_ERROR_NONE;
 
 608   r->pending_queries = 0;
 
 609   GRPC_CARES_TRACE_LOG(
 
 610       "request:%p c-ares grpc_dns_lookup_ares_locked_impl name=%s, "
 
 612       r, name, default_port);
 
 613   // Early out if the target is an ipv4 or ipv6 literal.
 
 614   if (resolve_as_ip_literal_locked(name, default_port, addrs)) {
 
 615     grpc_ares_complete_request_locked(r);
 
 618   // Early out if the target is localhost and we're on Windows.
 
 619   if (grpc_ares_maybe_resolve_localhost_manually_locked(name, default_port,
 
 621     grpc_ares_complete_request_locked(r);
 
 624   // Don't query for SRV and TXT records if the target is "localhost", so
 
 625   // as to cut down on lookups over the network, especially in tests:
 
 626   // https://github.com/grpc/proposal/pull/79
 
 627   if (target_matches_localhost(name)) {
 
 628     check_grpclb = false;
 
 629     r->service_config_json_out = nullptr;
 
 631   // Look up name using c-ares lib.
 
 632   grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
 
 633       r, dns_server, name, default_port, interested_parties, check_grpclb,
 
 634       query_timeout_ms, combiner);
 
 638 grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
 
 639     const char* dns_server, const char* name, const char* default_port,
 
 640     grpc_pollset_set* interested_parties, grpc_closure* on_done,
 
 641     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs,
 
 642     bool check_grpclb, char** service_config_json, int query_timeout_ms,
 
 643     grpc_combiner* combiner) = grpc_dns_lookup_ares_locked_impl;
 
 645 static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) {
 
 646   GPR_ASSERT(r != nullptr);
 
 647   if (r->ev_driver != nullptr) {
 
 648     grpc_ares_ev_driver_shutdown_locked(r->ev_driver);
 
 652 void (*grpc_cancel_ares_request_locked)(grpc_ares_request* r) =
 
 653     grpc_cancel_ares_request_locked_impl;
 
 655 // ares_library_init and ares_library_cleanup are currently no-op except under
 
 656 // Windows. Calling them may cause race conditions when other parts of the
 
 657 // binary calls these functions concurrently.
 
 659 grpc_error* grpc_ares_init(void) {
 
 660   int status = ares_library_init(ARES_LIB_INIT_ALL);
 
 661   if (status != ARES_SUCCESS) {
 
 663     gpr_asprintf(&error_msg, "ares_library_init failed: %s",
 
 664                  ares_strerror(status));
 
 665     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
 
 669   return GRPC_ERROR_NONE;
 
 672 void grpc_ares_cleanup(void) { ares_library_cleanup(); }
 
 674 grpc_error* grpc_ares_init(void) { return GRPC_ERROR_NONE; }
 
 675 void grpc_ares_cleanup(void) {}
 
 676 #endif  // GPR_WINDOWS
 
 679  * grpc_resolve_address_ares related structs and functions
 
 682 typedef struct grpc_resolve_address_ares_request {
 
 683   /* combiner that queries and related callbacks run under */
 
 684   grpc_combiner* combiner;
 
 685   /** the pointer to receive the resolved addresses */
 
 686   grpc_resolved_addresses** addrs_out;
 
 687   /** currently resolving addresses */
 
 688   grpc_core::UniquePtr<ServerAddressList> addresses;
 
 689   /** closure to call when the resolve_address_ares request completes */
 
 690   grpc_closure* on_resolve_address_done;
 
 691   /** a closure wrapping on_resolve_address_done, which should be invoked when
 
 692      the grpc_dns_lookup_ares_locked operation is done. */
 
 693   grpc_closure on_dns_lookup_done_locked;
 
 696   /* default port to use if none is specified */
 
 697   const char* default_port;
 
 698   /* pollset_set to be driven by */
 
 699   grpc_pollset_set* interested_parties;
 
 700   /* underlying ares_request that the query is performed on */
 
 701   grpc_ares_request* ares_request = nullptr;
 
 702 } grpc_resolve_address_ares_request;
 
 704 static void on_dns_lookup_done_locked(void* arg, grpc_error* error) {
 
 705   grpc_resolve_address_ares_request* r =
 
 706       static_cast<grpc_resolve_address_ares_request*>(arg);
 
 707   gpr_free(r->ares_request);
 
 708   grpc_resolved_addresses** resolved_addresses = r->addrs_out;
 
 709   if (r->addresses == nullptr || r->addresses->empty()) {
 
 710     *resolved_addresses = nullptr;
 
 712     *resolved_addresses = static_cast<grpc_resolved_addresses*>(
 
 713         gpr_zalloc(sizeof(grpc_resolved_addresses)));
 
 714     (*resolved_addresses)->naddrs = r->addresses->size();
 
 715     (*resolved_addresses)->addrs =
 
 716         static_cast<grpc_resolved_address*>(gpr_zalloc(
 
 717             sizeof(grpc_resolved_address) * (*resolved_addresses)->naddrs));
 
 718     for (size_t i = 0; i < (*resolved_addresses)->naddrs; ++i) {
 
 719       GPR_ASSERT(!(*r->addresses)[i].IsBalancer());
 
 720       memcpy(&(*resolved_addresses)->addrs[i], &(*r->addresses)[i].address(),
 
 721              sizeof(grpc_resolved_address));
 
 724   GRPC_CLOSURE_SCHED(r->on_resolve_address_done, GRPC_ERROR_REF(error));
 
 725   GRPC_COMBINER_UNREF(r->combiner, "on_dns_lookup_done_cb");
 
 726   grpc_core::Delete(r);
 
 729 static void grpc_resolve_address_invoke_dns_lookup_ares_locked(
 
 730     void* arg, grpc_error* unused_error) {
 
 731   grpc_resolve_address_ares_request* r =
 
 732       static_cast<grpc_resolve_address_ares_request*>(arg);
 
 733   r->ares_request = grpc_dns_lookup_ares_locked(
 
 734       nullptr /* dns_server */, r->name, r->default_port, r->interested_parties,
 
 735       &r->on_dns_lookup_done_locked, &r->addresses, false /* check_grpclb */,
 
 736       nullptr /* service_config_json */, GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS,
 
 740 static void grpc_resolve_address_ares_impl(const char* name,
 
 741                                            const char* default_port,
 
 742                                            grpc_pollset_set* interested_parties,
 
 743                                            grpc_closure* on_done,
 
 744                                            grpc_resolved_addresses** addrs) {
 
 745   grpc_resolve_address_ares_request* r =
 
 746       grpc_core::New<grpc_resolve_address_ares_request>();
 
 747   r->combiner = grpc_combiner_create();
 
 748   r->addrs_out = addrs;
 
 749   r->on_resolve_address_done = on_done;
 
 750   GRPC_CLOSURE_INIT(&r->on_dns_lookup_done_locked, on_dns_lookup_done_locked, r,
 
 751                     grpc_combiner_scheduler(r->combiner));
 
 753   r->default_port = default_port;
 
 754   r->interested_parties = interested_parties;
 
 756       GRPC_CLOSURE_CREATE(grpc_resolve_address_invoke_dns_lookup_ares_locked, r,
 
 757                           grpc_combiner_scheduler(r->combiner)),
 
 761 void (*grpc_resolve_address_ares)(
 
 762     const char* name, const char* default_port,
 
 763     grpc_pollset_set* interested_parties, grpc_closure* on_done,
 
 764     grpc_resolved_addresses** addrs) = grpc_resolve_address_ares_impl;
 
 766 #endif /* GRPC_ARES == 1 */